/*
 * BitSelect.java
 * 
 * last update: 15.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 *
 * Obs:  
 */

package engine;

class BitSelect extends WireSelection
{
	int start, end;
	BitVector b;
	GenericSelectorDescription target; //runtime info

	BitSelect(NameSpace ns, BitVector b, GenericSelectorDescription target){
		this(ns, b, target, b.msb, b.lsb);
	}

	BitSelect(NameSpace ns, BitVector b,
			GenericSelectorDescription target, int start, int end){
		super(ns);
		this.target = target;
		this.start = start;
		this.end = end;
		this.b = b;
		length = Math.abs(start-end)+1;
	}

	public Result evaluate()
	throws InterpretTimeException
	{
		return new BitVector(b, start, end);
	}

	public int length() {
		return length;
	}

	/**
	 * Returns the strength that drives this wire.
	 * @see WireSelection.getStrength
	 * @exception ClassCastException if the BitSelect does not reffer to a wire.
	 */
	public int getStrength(int bitIndex)throws ClassCastException{
		Wire w = (Wire)b;
		bitIndex  = start >= end ? bitIndex + end : end - bitIndex; //translate
		//bitIndex into
		//wire's indexes
		return (w.getBit(bitIndex) << 16) |
		((int)w.getStrength(bitIndex) & 0x000000ff);
	}

	public void getStrengths(byte s[], int index) {
		try {
			Wire w = (Wire)b;
			for(int i = 0, bitIndex = end, inc = start >= end ? 1 : -1 ; i < length;
			i++, bitIndex += inc)
				s[index++] = w.getStrength(bitIndex);
		} catch (ClassCastException cex) {
			byte ds = Strength.defaultStrength;
			for(int i = 0; i < length; i++)
				s[index++] = ds;
		}
	}

	public void setStrengths(byte []s, int i) {
		throw new Error ("bug: BitSelect.setStrength called ! target: " + target);
	}

	public void assign(Result r)
	throws InterpretTimeException
	{
		BitVector val = r.getBits();
		if(length > val.n ) val.expandS(length); //signed axpansion here
		if(length < val.n ) val.trunc(length);
		set(val, val.msb, val.lsb);
	}

	void set(BitVector x, int start, int end)
	throws InterpretTimeException
	{
		b.attrib(this.start, this.end, x, start, end);
	}

	void assign(Result r, byte[] strengths)throws InterpretTimeException{
		throw new InterpretTimeException(this + " cannot be continuously assigned");
	}

	public String toString(){
		return  target != null ? target.toString() : "BitSelect: " + b +
				" start: " + start + " end: " + end;
	}

	synchronized void addMonitor(Monitor m){
		b.addMonitor(m);
	}

	/**
	 *  @see WireSelection.release
	 */
	void release(){}

	/**
	 *  @see WireSelection.reatach
	 */
	void reatach(){}

	/**
	 *  @see WireSelection.reatach
	 */
	void breakSelection(WireSelection bits[], int startIndex) {
		int i = start, inc = start >= end ? -1 : 1;
		while(true) {
			bits[startIndex++] = new BitSelect(ns, b, target, i, i);
			if (i == end) break;
			i += inc;
		}
	}
}






